# 数据格式的转换
import json
import os
# 格式输出，例如保留原数据的格式
import pprint

# moviepy是一个视频处理的库，AudioFileClip:音频处理, VideoFileClip:视频处理
from moviepy.editor import AudioFileClip, VideoFileClip
# 网页数据的请求
import requests
# 正则表达式
import re

cookies = {
    'buvid3': '84716D57-9C75-5B7A-85A9-FBD644A6940996851infoc',
    'b_nut': '1718810996',
    'CURRENT_FNVAL': '4048',
    '_uuid': 'EBB126F5-BD1A-3C8C-CEE7-145CC9ACF4CC67682infoc',
    'buvid4': 'A94473FE-E8A1-00F5-1A29-25E4658325A198477-024061915-fmaQuYosI7O9T4jOxoGBKlglpox4xqlt8WaWxoJnMLb5ee7WO%2BHNrE%2BBUXJ%2BwvNj',
    'buvid_fp': '7eac870a954dc97e713550117e6a88b1',
    'rpdid': '0zbfALaLNK|pEhW3Qgj|3rg|3w1SjXg3',
    'DedeUserID': '475514092',
    'DedeUserID__ckMd5': 'c7204cc35ac16801',
    'enable_web_push': 'DISABLE',
    'header_theme_version': 'CLOSE',
    'home_feed_column': '5',
    'browser_resolution': '1536-714',
    'bmg_af_switch': '1',
    'bmg_src_def_domain': 'i1.hdslb.com',
    'bp_t_offset_475514092': '948310606950170624',
    'bili_ticket': 'eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTk5MTEzMzcsImlhdCI6MTcxOTY1MjA3NywicGx0IjotMX0.YBDI8Hq_3dDniv-MyGCpEEMKByQmrp2_BiTP6W4kyHU',
    'bili_ticket_expires': '1719911277',
    'b_lsid': '739C8332_190686D0054',
    'SESSDATA': '325ebdfe%2C1735295447%2Cefb1c%2A62CjB0ilTdC0RhWLmUiJXZYjMtKBrwhEFcVpIN_9z8w007OqYUJofUDqnpxVOLqRLS-ZoSVmdqVWtMdkUxMmxsSG5CMFlsMHc4NHJ2WU5HaWtJRXVabkY0X1NEUlBvSEpsOG5ST01lcHBVazZwTktmN2tCamJLdVoyOHBha1RaRUdCdkRvWVU5cUZnIIEC',
    'bili_jct': '3df7633c4811ce6934f35d05ca39f065',
    'sid': 'qkq1sd62',
}

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'cache-control': 'no-cache',
    # 'cookie': 'buvid3=84716D57-9C75-5B7A-85A9-FBD644A6940996851infoc; b_nut=1718810996; CURRENT_FNVAL=4048; _uuid=EBB126F5-BD1A-3C8C-CEE7-145CC9ACF4CC67682infoc; buvid4=A94473FE-E8A1-00F5-1A29-25E4658325A198477-024061915-fmaQuYosI7O9T4jOxoGBKlglpox4xqlt8WaWxoJnMLb5ee7WO%2BHNrE%2BBUXJ%2BwvNj; buvid_fp=7eac870a954dc97e713550117e6a88b1; rpdid=0zbfALaLNK|pEhW3Qgj|3rg|3w1SjXg3; DedeUserID=475514092; DedeUserID__ckMd5=c7204cc35ac16801; enable_web_push=DISABLE; header_theme_version=CLOSE; home_feed_column=5; browser_resolution=1536-714; bmg_af_switch=1; bmg_src_def_domain=i1.hdslb.com; bp_t_offset_475514092=948310606950170624; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTk5MTEzMzcsImlhdCI6MTcxOTY1MjA3NywicGx0IjotMX0.YBDI8Hq_3dDniv-MyGCpEEMKByQmrp2_BiTP6W4kyHU; bili_ticket_expires=1719911277; b_lsid=739C8332_190686D0054; SESSDATA=325ebdfe%2C1735295447%2Cefb1c%2A62CjB0ilTdC0RhWLmUiJXZYjMtKBrwhEFcVpIN_9z8w007OqYUJofUDqnpxVOLqRLS-ZoSVmdqVWtMdkUxMmxsSG5CMFlsMHc4NHJ2WU5HaWtJRXVabkY0X1NEUlBvSEpsOG5ST01lcHBVazZwTktmN2tCamJLdVoyOHBha1RaRUdCdkRvWVU5cUZnIIEC; bili_jct=3df7633c4811ce6934f35d05ca39f065; sid=qkq1sd62',
    'pragma': 'no-cache',
    'priority': 'u=0, i',
    'referer': 'https://www.bilibili.com/', # 添加防盗链
    'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Microsoft Edge";v="126"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',
}

params = {
    'spm_id_from': '333.1007.tianma.1-2-2.click',
    'vd_source': '503fc131f183cd6c664b27d8beda0d1a',
}

def send_request(url):
    try:
        response = requests.get(url, cookies=cookies, headers=headers)
        response.raise_for_status()  # 判断请求是否成功：如果不是200，产生异常requests.HTTPError
        return response
    except:
        return "数据请求失败"

def send_video_data(html_data):
    title=re.findall('" title="(.*?)" class',html_data)[0]
    # 遇到特殊字符则替换
    file_name=re.sub(r'[\/:*?"<>|]','',title)
    # print(title)
    source_data=re.findall(r'<script>window.__playinfo__=(.*?)</script>',html_data)[0]
    # 转换成json格式
    json_data=json.loads(source_data)
    # pprint.pprint(json_data) # json格式打印
    # 获取音频数据链接
    audio_url=json_data['data']['dash']['audio'][0]['baseUrl']
    # 获取视频数据链接
    video_url=json_data['data']['dash']['video'][0]['baseUrl']
    # 存放至列表中
    video_data=[file_name,audio_url,video_url]
    return video_data

def save_data(file_name, audio_url, video_url):
    # 请求数据，获取二进制数据
    print('正在请求音频数据')
    audio_data = send_request(audio_url).content
    print('正在请求视频数据')
    video_data = send_request(video_url).content
    # 将音频数据和视频数据保存至文件中
    with open(file_name + '.mp3', mode='wb') as f:
        f.write(audio_data)
        print('正在保存音频数据')
    with open(file_name + '.mp4', mode='wb') as f:
        f.write(video_data)
        print('正在保存视频数据')

def merge_data(video_name,file_name="output3"):
    print("视频合成开始:",video_name)
    audioclip=AudioFileClip(video_name+'.mp3')
    videoclip=VideoFileClip(video_name+'.mp4')
    # 获取视频和音频的时长
    video_time=videoclip.duration
    audio_time=audioclip.duration
    # 对视频或者音频进行裁剪
    if video_time>audio_time:
        # 视频时长>音频时长，对视频进行截取
        videoclip_new=videoclip.subclip(0,audio_time)
        audioclip_new=audioclip
    else:
        # 音频时长>视频时长，对音频进行截取
        videoclip_new = videoclip
        audioclip_new = audioclip.subclip(0, video_time)
    # 视频中加入音频
    video_with_new_audio=videoclip_new.set_audio(audioclip_new)
    # 写入到新的视频文件中
    video_with_new_audio.write_videofile("{}.mp4".format(file_name),
                                         codec='libx264',
                                         audio_codec='aac',
                                         temp_audiofile='temp-video.m4a',
                                         remove_temp=True
                                         )
    print('视频合成结束:', video_name)

if __name__=="__main__":
    code=input("请输入视频BV号【提示：url地址上的BV开头编号，例如：BV1jieteQE2r】：")

    url = 'https://www.bilibili.com/video/{}/'.format(code)
    response = send_request(url)
    # response.encoding = requests.utils.get_encodings_from_content(response.text)[0]
    html_data = response.text
    video_data = send_video_data(html_data)
    save_data(video_data[0], video_data[1], video_data[2])
    file_name = input("请输入视频文件名：")
    merge_data(video_data[0],file_name)
    os.remove(f"{video_data[0]}.mp4")
    os.remove(f"{video_data[0]}.mp3")


